package utils

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

type HttpHandleStruct struct {
	Host   string      // http://xxxx.xx.xx.xx
	Uri    string      // 以/ 为开头的str
	Header http.Header // map[string][]string
	Params url.Values  // 拼接到url中的参数
	Body []byte // post参数
}

func NewRequestStruct(host, uri string) *HttpHandleStruct {
	if strings.HasPrefix(uri, "/") {

		return &HttpHandleStruct{Host: host,
			Uri:    uri,
			Header: make(http.Header),
			Params: make(url.Values),
			Body: *new([]byte),
		}
	} else {
		return nil
	}
}

//	url.Values{}
//	return &HttpHandleStruct{}
//}

// 发起get请求 返回请求结果，错误
func (h *HttpHandleStruct) Get() ([]byte, error) {
	apiUrl := fmt.Sprintf("%s%s", h.Host, h.Uri)
	client := &http.Client{}
	var req *http.Request
	var err error
	// 有参数的话设置
	if len(h.Params) > 0 {
		data := h.Params.Encode()
		//fmt.Println(data)
		req, err = http.NewRequest("GET", fmt.Sprintf("%s?%s",apiUrl,data), nil)
		if err != nil {
			//fmt.Println(err.Error())
			return  nil, err
		}

	} else {
		req, err = http.NewRequest("GET", apiUrl, nil)
		if err != nil {
			//fmt.Println(err.Error())
			return nil, err
		}
		//log.Println("requestUrl",req.URL)
	}

	// 设置header
	if len(h.Header) > 0 {
		for headerKey, headerValue := range h.Header {
			fmt.Println("headerKey,headerValue", headerKey, headerValue)
			if len(headerValue) == 1 {
				req.Header.Add(headerKey, headerValue[0])
			} else if len(headerValue) > 1 {
				req.Header.Add(headerKey, strings.Join(headerValue, ";"))
			}
		}

	}
	log.Println(req.URL)
	resp, err := client.Do(req)
	if err != nil {
		log.Println("request  failed,err: ", err.Error())
		return nil,err
	}
	body, err := ioutil.ReadAll(resp.Body)
	return body,err
	//defer resp.Body.Close()
	//if parse{
	//	result, err := ParseResponse(resp)
	//	return resp.StatusCode, result, err
	//}else{
	//	body, err := ioutil.ReadAll(resp.Body)
	//	fmt.Printf("%s",body)
	//	return resp.StatusCode,map[string]interface{}{"response":body},err
	//}
}

// 发起get请求 返回状态码，body，错误
func (h *HttpHandleStruct) Post(parse bool) (int, map[string]interface{}, error) {
	apiUrl := fmt.Sprintf("%s%s", h.Host, h.Uri)

	client := &http.Client{}
	var req *http.Request
	var err error
	// 有参数的话设置
	if len(h.Params) > 0 {
		data := h.Params.Encode()
		fmt.Println(data)
		req, err = http.NewRequest("POST", fmt.Sprintf("%s?%s",apiUrl,data), bytes.NewReader(h.Body))
		if err != nil {
			fmt.Println(err.Error())
			return 0, nil, err
		}
		fmt.Println(req.RequestURI, "fdsafdsaf---------")

	} else {
		req, err = http.NewRequest("POST", apiUrl, bytes.NewReader(h.Body))
		if err != nil {
			fmt.Println(err.Error())
			return 0, nil, err
		}

		fmt.Println(req.URL, "fdsafdsaf")

	}

	// 设置header
	if len(h.Header) > 0 {
		for headerKey, headerValue := range h.Header {
			fmt.Println("headerKey,headerValue", headerKey, headerValue)
			if len(headerValue) == 1 {
				req.Header.Add(headerKey, headerValue[0])
			} else if len(headerValue) > 1 {
				req.Header.Add(headerKey, strings.Join(headerValue, ";"))
			}
		}

	}
	fmt.Printf("header %v", req.Header)
	fmt.Println(req.RequestURI,"123456789")
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("request  failed,err:\n", err.Error())
		return resp.StatusCode, nil, err
	}
	defer resp.Body.Close()
	if parse{
		result, err := ParseResponse(resp)
		return resp.StatusCode, result, err
	}else{
		return resp.StatusCode,map[string]interface{}{"response":resp.Body},err
	}


}

func ParseResponse(response *http.Response) (map[string]interface{}, error) {
	var result map[string]interface{}
	body, err := ioutil.ReadAll(response.Body)
	defer response.Body.Close()
	//fmt.Printf("-----%s---",body)
	if err == nil {
		err = json.Unmarshal(body, &result)
	}
	return result, err
}

func HMACSHA256(keyStr, value string)string{
	key := []byte(keyStr)
	mac := hmac.New(sha256.New, key)
	mac.Write([]byte(value))
	//进行base64编码
	res := base64.StdEncoding.EncodeToString(mac.Sum(nil))

	return res
}

type ActionsInputs struct {
	method  string                 `json:"method" binding:"required"`
	url     string                 `json:"url" binding:"required"`
	headers map[string]string      `json:"headers"`
	query   map[string]string      `json:"query"` //GET请求参数 会追加 did字段（主运行任务id） 会追加 tid字段（原子运行任务id
	body    map[string]interface{} `json:"body"`  //POST请求参数 会追加 did字段（主运行任务id）会追加 tid字段（原子运行任务id
}


func Base64(m []byte)string{
	return base64.StdEncoding.EncodeToString(m)
}

// 上传文件的请求
func NewfileUploadRequest(url, method string,path string)([]byte,error){

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)
	file, errFile1 := os.Open(path)
	defer file.Close()
	part1, errFile1 := writer.CreateFormFile("filename",filepath.Base(path))
	_, errFile1 = io.Copy(part1, file)
	if errFile1 != nil {
		fmt.Println(errFile1)
		return nil,errFile1
	}
	err := writer.Close()
	if err != nil {
		fmt.Println(err)
		return nil,err
	}

	client := &http.Client {
	}
	req, err := http.NewRequest(method, url, payload)

	if err != nil {
		fmt.Println(err)
		return nil,err
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return nil,err
	}
	defer res.Body.Close()

	return ioutil.ReadAll(res.Body)
}